const ownerTables = {
    "ou"          : "backend_operation_units",
    "member"      : "slime_members",
    "store"       : "slime_stores",
    "brand_sku"   : "slime_brand_skus",
    "trader_sku"  : "slime_trader_skus"
};

const profileIndex = {
    "member"     : {},
    "store"      : {},
    "ou"         : {},
    "brand_sku"  : {},
    "trader_sku" : {}
};


var getProfileParameters  =  function({lab, owner, name, table, type , id_field, profile_types = ["profile","activity"] , default_value , exporter, export_fields = []}) {
    if (!name || !table || !type || !owner || !lab) {
        throw @lab.errors.invalid_parameters;
    }
    if (!lab.models[table] ){
        throw new Error("Table Not Found : " + table);
    }
    if (profile_types.indexOf(type) < 0) {
        throw @lab.errors.invalid_parameters;
    }

    if (!profileIndex[owner]) {
        throw @lab.errors.not_support;
    }

    if (!lab.models[table][id_field]) {
        throw new Error("Table ID Field Not Found : " + id_field + "@" + table );
    }

    if (!export_fields.reduce(function(result, key){
        return result && lab.models[table][key];
    },true)) {
        throw new Error("Key Not Found : " + key + "@" + table);
    }

    if (profileIndex[owner][name]) {
        @warn("Profile " + name + "@" + owner + " already exists");
    } else {
        @info("Register " + name + "@" + owner + " profile module");
    }

    profileIndex[owner][name] = {
        name, 
        table, 
        type, 
        id_field,
        default_value, 
        exporter,
        exports  : exporter ? undefined : (export_fields.length ? export_fields : undefined)
    }

    return profileIndex[owner][name];
};


var getActivities = function(lab, field, owner, start , limit) {

    var condition = {};
    condition[field.id_field] = owner.id;

    return lab.sqlite.query("select count(*) as total from " + field.table + " where " + field.id_field + " = ?", owner.id).then(function(result){

        if (result.records.length) {
            
            this.pool.total = result.records[0].total;
            if (this.pool.total){
                return lab.sqlite.find(field.table, condition, limit, start);
            } else {
                this.next({
                    records : []
                });
            }
            
        } else {

            this.next({
                records : []
            });

        }

    }).then(function(result){

        this.next({
            total : this.pool.total, 
            list  : result.records.map(function(record){
                if (field.exports){
                    return field.exports.reduce(function(result,entry){
                        result[entry] = record[entry];
                        return result;
                    },{})
                } else {
                    return record;
                }
            })
        });

    })
}

var getProfile = function(lab, index, owner) {
    var output    = {};
    return @.async.all(@.keys(index),-1, function(field_name){

        var field = index[field_name];

        return @.async(function(){

            if (field.exporter) {

                return field.exporter(lab, owner);

            } else {

                var condition = {};
                condition[field.id_field] = owner.id;

                switch (field.type){
                    case "profile" : {
                        return lab.find(field.table, condition).then(function(profile){
                            if (profile) {
                                if (field.exports) {
                                    this.next(field.exports.reduce(function(result,entry){
                                        result[entry] = profile[entry];
                                        return result;
                                    },{}));
                                } else {
                                    this.next(profile);
                                }
                            } else if (field.default_value) {

                                if (@.is(field.default_value,Function)) {
                                    return field.default_value(lab,owner);
                                } else {
                                    
                                    var create_default_value = @.merge.simple({},field.default_value);
                                    create_default_value[field.id_field] = owner.id;
                                    create_default_value.create_date     = Date.now();
                                    create_default_value.last_update     = Date.now();

                                    return lab.create(field.table,create_default_value).then(function(created_value){
                                        if (field.exports) {
                                            this.next(field.exports.reduce(function(result,entry){
                                                result[entry] = created_value[entry];
                                                return result;
                                            },{}));
                                        } else {
                                            this.next(created_value);
                                        }
                                    });

                                }
                            } else {
                                this.next();
                            }
                            
                        });
                    };
                    case "activity" : {
                        return getActivities(lab, field, owner, 0, 10);
                    };
                    default : {
                        return this.next();
                    }
                }
            }

        }).then(function(profile){

            if (profile) {
                output[field_name] = profile;
            }

            this.next();
        })

    }).resolve(output);
}

// 一个前端API请求， 分别去请求一堆类似profile东西，还是请求一个profile对象，里面不同域返回回来。

module.exports = function(lab) {
    return {
        @getActivities : function({namespace, owner, owner_id, start = 0 , limit = 10 }){

            if (!namespace) {
                throw @lab.errors.invalid_parameters;
            }

            var result = namespace.split(".").reduce(function(result, name){
                if (result && result[name]) {
                    return result[name];
                } else {
                    return null;
                }
            },profileIndex);

            if (!result || result == profileIndex || result.type !== "activity") {
                throw @lab.errors.object_not_found;
            }

            return @.async(function(){

                if (owner) {
                    this.next(owner);
                } else {
                    return lab.find(ownerTables[namespace[0]], owner_id);
                }

            }).then(function(selected_owner){

                if (!selected_owner) {
                    throw @lab.errors.object_not_found;
                }

                if (result.exporter) {
                    return result.exporter(lab , selected_owner, start , limit);
                } else {
                    return getActivities(lab, result, selected_owner, start, limit);
                }
            }); 
            
        },
        @getProfile : function({namespace, owner, owner_id}){
            if (!namespace || !profileIndex[namespace]) {
                throw @lab.errors.invalid_parameters;
            }

            return @.async(function(){
                
                if (owner) {
                    this.next(owner);
                } else {
                    return lab.find(ownerTables[namespace], owner_id);
                }

            }).then(function(selected_owner){

                if (!selected_owner) {
                    throw @lab.errors.object_not_found;
                }

                return getProfile(lab , profileIndex[namespace], selected_owner);
            });
            
        },
        @getMemberProfile : function(currentMember){
            return getProfile(lab,profileIndex.member, currentMember);
        },
        @getStoreProfile : function(currentStore){
            return getProfile(lab,profileIndex.store, currentStore);
        },
        @registerMemberProfile : function({name, table, id_field = "member_id" , type = "profile", export_fields = [], exporter, default_value}) {
            return getProfileParameters({lab, owner : "member", id_field,name, table, type , export_fields, exporter, default_value});
        },
        @registerStoreProfile : function({name, table, id_field = "store_id" , type = "profile", export_fields = [], exporter, default_value}) {
            return getProfileParameters({lab, owner : "store", id_field,name, table, type, export_fields, exporter, default_value});
        },
        @registerOUProfile : function({name, table, id_field = "ouid" , type = "profile", export_fields = [], exporter, default_value}) {
            return getProfileParameters({lab, owner : "ou", id_field,name,  table, type , export_fields, exporter, default_value});
        },
        @registerBrandSKUProfile : function({name, table, id_field = "sku_id" , type = "profile", export_fields = [], exporter, default_value}) {
            return getProfileParameters({lab, owner : "brand_sku", id_field,name,  table, type , export_fields, exporter, default_value});
        },
        @registerTraderSKUProfile : function({name, table, id_field = "sku_id" , type = "profile", export_fields = [], exporter, default_value}) {
            return getProfileParameters({lab, owner : "trader_sku", id_field,name,  table, type , export_fields, exporter, default_value});
        }
    }
}